<template>
  <div class="login-form-wrap">
    <div class="login-title">F云盘</div>
    <div class="login-box">
      <div class="login-switch-wrap" :class="[loginType]">
        <template v-if="loginType === 'verifyCode'">
          <span class="back" @click="handleClickBack">
            <svg
                data-v-64aaa9fb=""
                xmlns="http://www.w3.org/2000/svg"
                xmlns:xlink="http://www.w3.org/1999/xlink"
                fill="none"
                version="1.1"
                width="24"
                height="24"
                viewBox="0 0 24 24"
            >
              <defs data-v-64aaa9fb="">
                <clipPath data-v-64aaa9fb="" id="master_svg0_1423_115618">
                  <rect data-v-64aaa9fb="" x="0" y="0" width="24" height="24" rx="0"></rect>
                </clipPath>
              </defs>
              <g data-v-64aaa9fb="" clip-path="url(#master_svg0_1423_115618)">
                <g data-v-64aaa9fb="">
                  <path
                      data-v-64aaa9fb=""
                      d="M13.744936875,19.9679044921875C13.744936875,19.9679044921875,14.603526875,19.0321044921875,14.603526875,19.0321044921875C14.603526875,19.0321044921875,6.939086875,12.0000044921875,6.939086875,12.0000044921875C6.939086875,12.0000044921875,14.603526875,4.9679034921875,14.603526875,4.9679034921875C14.603526875,4.9679034921875,13.744936875,4.0321044921875,13.744936875,4.0321044921875C13.744936875,4.0321044921875,5.060546875,12.0000044921875,5.060546875,12.0000044921875C5.060546875,12.0000044921875,13.744936875,19.9679044921875,13.744936875,19.9679044921875Z"
                      fill="#25262B"
                      fill-opacity="0.7200000286102295"
                  ></path>
                </g>
              </g>
            </svg>
          </span>
          <span class="center-title">短信验证</span>
        </template>
        <template v-else>
          <div
              :class="['login-switch-text left', loginType === 'code' ? 'active' : '']"
              @click="handleChangeLoginType('code')"
          >
            扫码登录
          </div>
          <div
              :class="['login-switch-text right', loginType === 'account' ? 'active' : '']"
              @click="handleChangeLoginType('account')"
          >
            账号登录
          </div>
        </template>
      </div>
      <div class="login-form-content" :class="['content-' + loginType]">
        <!--        扫码登录-->
        <template v-if="loginType === 'code'">
          <div class="login-code-wrap">
            <div class="login-code-img">
              <canvas id="scan-canvas" class="scan-canvas"></canvas>
            </div>
          </div>
          <div class="login-code-description">请使用F云盘App扫码</div>
          <div class="login-checkbox-auto-login">
            <ElCheckbox v-model="pageData.autoLogin"/>
            <span @click="handleClickAutoLogin">下次自动登录</span>
          </div>
          <div class="login-register-account">
            <span @click="handleRegister">还没有账号，注册一个</span>
          </div>
        </template>
        <template v-else-if="loginType === 'account'">
          <div class="login-input-mobile">
            <ElInput
                v-model="pageData.mobile"
                placeholder="请输入手机号"
                clearable
                @keyup.enter="handleSubmit"
            />
          </div>
          <div class="login-input-pwd">
            <ElInput
                v-model="pageData.pwd"
                placeholder="请输入密码"
                clearable
                show-password
                @keyup.enter="handleSubmit"
            />
          </div>
          <div class="login-btn-submit">
            <ElButton class="login-submit" @click="handleSubmit()">登录</ElButton>
          </div>
          <div class="login-change-login">
            <div class="login-checkbox-auto-login">
              <ElCheckbox v-model="pageData.autoLogin"/>
              <span @click="handleClickAutoLogin">下次自动登录</span>
            </div>
            <div class="login-verify-type">
              <span @click="handleChangeLoginType('verifyCode')">验证码登录</span>
            </div>
          </div>
          <div class="login-register-account">
            <span @click="handleRegister">还没有账号，注册一个</span>
          </div>
        </template>
        <template v-else-if="loginType === 'verifyCode'">
          <div class="login-input-mobile">
            <ElInput
                v-model="pageData.mobile"
                placeholder="请输入手机号"
                clearable
                @keyup.enter="handleSubmit"
            />
          </div>
          <div class="login-input-verify-code">
            <ElInput
                v-model="pageData.verifyCode"
                placeholder="请输入验证码"
                clearable
                @keyup.enter="handleSubmit"
            />
            <ElButton
                class="verify-code-btn"
                @click="handleSendVerifyCode"
                :disabled="!pageData.showSendMsgBtn"
            >
              {{ pageData.showSendMsgBtn ? '发送验证码' : `重新发送(${pageData.restTime})` }}
            </ElButton>
          </div>
          <div class="login-btn-submit">
            <ElButton class="login-submit" @click="handleSubmit()">登录</ElButton>
          </div>
          <div class="login-checkbox-auto-login">
            <ElCheckbox v-model="pageData.service"/>
            <span @click="handleClickService">
              未注册手机登录时会自动创建新账号，我已阅读并同意
              <span class="highlight-text">服务协议</span>
              和
              <span class="highlight-text">隐私权条款</span>
            </span>
          </div>
          <div class="login-forgot-pwd">
            <div class="login-checkbox-auto-login">
              <ElCheckbox v-model="pageData.autoLogin"/>
              <span @click="handleClickAutoLogin">下次自动登录</span>
            </div>
            <div class="login-forgot">
              <span @click="handleFindPassword">找回密码</span>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
  <XhhDialog
      title="找回密码"
      v-model="findPasswordVisible"
      width="400px"
      class="large-input-dialog"
      @confirm="handleConfirmSend"
  >
    <el-tabs class="valid-type-tabs" v-model="activeName">
      <el-tab-pane label="手机验证" name="mobile"></el-tab-pane>
      <el-tab-pane label="邮箱验证" name="email"></el-tab-pane>
    </el-tabs>
    <template v-if="activeName === 'mobile'">
      <div class="line-text-item">请输入您注册账号时填写的手机号</div>
      <el-input class="large-input" v-model="mobile" clearable></el-input>
    </template>
    <template v-else-if="activeName === 'email'">
      <div class="line-text-item">请输入您注册账号时填写的邮箱</div>
      <el-input class="large-input" v-model="email" clearable></el-input>
    </template>
    <div class="line-text-item">请填写验证码</div>
    <common-validate-combination
        v-model="smsCode"
        @enter="handleConfirmSend"
    ></common-validate-combination>
    <template v-slot:footer>
      <el-button @click="handleCancelSend">取消</el-button>
      <el-button :disabled="sendBtnInfo.disabled" @click="handleConfirmSend">
        {{ sendBtnInfo.showWait ? `重新发送(${sendBtnInfo.waitNumber})` : '确定' }}
      </el-button>
    </template>
  </XhhDialog>
  <XhhDialog
      :title="activeLabel + '验证码'"
      v-model="validCodeVisible"
      width="400px"
      class="large-input-dialog"
      @confirm="handleConfirmValid"
  >
    <div class="line-text-item">请输入您的{{ activeLabel }}收到的验证码</div>
    <el-input
        class="large-input"
        v-model="validCode"
        clearable
        @keyup.enter="handleConfirmValid"
    ></el-input>
  </XhhDialog>
  <XhhDialog
      title="重置密码"
      v-model="resetPassVisible"
      width="400px"
      class="large-input-dialog"
      @confirm="handleConfirmReset"
  >
    <div class="line-text-item">请设置您的密码</div>
    <el-input class="large-input" v-model="resetPassword" show-password clearable></el-input>
    <div class="line-text-item">请确认您的密码</div>
    <el-input
        class="large-input"
        v-model="resetPasswordConfirm"
        show-password
        clearable
        @keyup.enter="handleConfirmReset"
    ></el-input>
  </XhhDialog>
</template>
<script lang="ts" setup>
import {computed, ref, onMounted, nextTick} from 'vue'
import qrious from 'qrious'
import req, {hostApi} from '@/utils/req/axios.js'
import {tip} from '@tip'
import {useRouter} from 'vue-router'
import {TOKEN_KEY, USERINFO_KEY} from '@/utils/constants'
import urls from '@/utils/constants/urls.js'
import {buildTree} from '@/utils/common/fns/array'
import useGlobalStore from '@/stores/global.js'
import CommonValidateCombination from '../common/validate-combination.vue'
import emitter from '@/utils/common/event-bus/index.js'
import {EVENT_BUS_REFRESH_SMS_CODE} from '@/utils/constants/event-bus.js'
import regexp from '@/utils/constants/regexp.js'

const globalStore = useGlobalStore()

const router = useRouter()
onMounted(() => {
  createQr()
})

function createQr() {
  new qrious({
    element: document.getElementById('scan-canvas'),
    value: hostApi + urls.v1.system.auth.scan2login,
  })
}

const loginType = ref('account')
const pageData = ref({
  mobile: '',
  pwd: '',
  verifyCode: '',
  autoLogin: false,
  service: false,
  restTime: 59,
  showSendMsgBtn: true,
})

async function handleChangeLoginType(argLoginType) {
  loginType.value = argLoginType
  await nextTick()
  if (argLoginType === 'code') {
    // 刷新二维码
    createQr()
  }
}

function handleClickAutoLogin() {
  pageData.value.autoLogin = !pageData.value.autoLogin
}

function handleClickService() {
  pageData.value.service = !pageData.value.service
}

const findPasswordVisible = ref(false)
const email = ref('')
const mobile = ref('')
const smsCode = ref('')

function handleFindPassword() {
  email.value = ''
  smsCode.value = ''
  findPasswordVisible.value = true
}

const validCode = ref('')
const resetPassVisible = ref(false)

async function handleConfirmValid() {
  if (!validCode.value) {
    tip({ message: `请输入${activeLabel.value}收到的验证码`, type: 'error' })
    return
  }
  if (activeName.value === 'mobile') {
    await req.post(urls.v1.system.mobile.valid, {
      mobile: mobile.value,
      validCode: validCode.value,
    })
  } else {
    await req.post(urls.v1.system.email.valid, {
      email: email.value,
      validCode: validCode.value,
    })
  }
  validCodeVisible.value = false
  // 验证成功之后，弹出重置密码的弹窗
  resetPassVisible.value = true
}

const resetPassword = ref('')
const resetPasswordConfirm = ref('')

async function handleConfirmReset() {
  // 判断两次密码是否相同，发送请求，修改密码
  if (resetPassword.value !== resetPasswordConfirm.value) {
    tip({ message: '两次输入的密码不相同', type: 'error' })
    return
  }
  await req.post(urls.v1.system.auth.resetPassword, {
    email: email.value,
    password: resetPassword.value,
  })
  resetPassVisible.value = false
}

const validCodeVisible = ref(false)
const activeName = ref('mobile')
const activeLabel = computed(() => (activeName.value === 'mobile' ? '手机' : '邮箱'))
const sendBtnInfo = ref({
  disabled: false,
  waitNumber: 0,
  showWait: false,
})

let countdownInterval

function startCountdown() {
  clearInterval(countdownInterval)
  countdownInterval = setInterval(() => {
    if (sendBtnInfo.value.waitNumber === 0) {
      clearInterval(countdownInterval)
      sendBtnInfo.value = {
        disabled: false,
        waitNumber: 0,
        showWait: false,
      }
      return
    }
    sendBtnInfo.value.waitNumber = sendBtnInfo.value.waitNumber - 1
  }, 1000)
}

function handleCancelSend() {
  findPasswordVisible.value = false
}

async function handleConfirmSend() {
  if (activeName.value === 'mobile') {
    if (!mobile.value) {
      tip({ message: '请输入手机号', type: 'error' })
      return
    }
    if (!regexp.mobile.test(mobile.value)) {
      tip({ message: '请输入符合规范的手机号', type: 'error' })
      return
    }
  } else if (activeName.value === 'email') {
    if (!email.value) {
      tip({ message: '请输入邮箱', type: 'error' })
      return
    }
    if (!regexp.email.test(email.value)) {
      tip({ message: '请输入符合规范的邮箱', type: 'error' })
      return
    }
  }
  if (!smsCode.value) {
    tip({ message: '请输入验证码', type: 'error' })
    return
  }
  if (activeName.value === 'mobile') {
    // 按钮改为禁用，且出现倒计时
    sendBtnInfo.value = {
      disabled: true,
      waitNumber: 60,
      showWait: true,
    }
    startCountdown()
  }
  const res =
      activeName.value === 'email'
          ? await req.post(
              urls.v1.system.email.send,
              {
                email: email.value,
                smsCode: smsCode.value,
              },
              { _isReturnOrigin: true },
          )
          : await req.post(
              urls.v1.system.mobile.send,
              {
                mobile: mobile.value,
                smsCode: smsCode.value,
              },
              { _isReturnOrigin: true },
          )
  if (res.errorCode === -1) {
    // 表示验证码输入有误，刷新验证码
    emitter.emit(EVENT_BUS_REFRESH_SMS_CODE)
    tip({ message: '验证码输入错误', type: 'error' })
    return
  } else if (res.errorCode === -2) {
    emitter.emit(EVENT_BUS_REFRESH_SMS_CODE)
    tip({ message: '邮件发送异常，请联系管理员', type: 'error' })
    return
  } else if (res.errorCode === -3) {
    emitter.emit(EVENT_BUS_REFRESH_SMS_CODE)
    tip({ message: '短信发送异常，请联系管理员', type: 'error' })
    return
  } else if (res.errorCode === -4) {
    emitter.emit(EVENT_BUS_REFRESH_SMS_CODE)
    sendBtnInfo.value = {
      disabled: true,
      waitNumber: res.data,
      showWait: true,
    }
    startCountdown()
    tip({ message: '业务过于繁忙，请稍等', type: 'error' })
    return
  }
  // 邮件发送成功
  tip({
    message: `${activeName.value === 'mobile' ? '短信' : '邮件'}已经发送成功`,
    type: 'success',
  })
  findPasswordVisible.value = false
  // 弹出验证邮件验证码的界面
  validCodeVisible.value = true
}

async function handleSubmit() {
  if (loginType.value === 'verifyCode') {
    if (!pageData.value.service) {
      tip({ message: '请同意服务协议', type: 'warning' })
      return
    }
    if (!validPhone()) {
      return
    }
    if (!validVerifyCode()) {
      return
    }
    const res = await req.post(urls.v1.system.auth.loginOrRegister, {
      userName: pageData.value.mobile,
      verifyCode: pageData.value.verifyCode,
    })
    afterLogin(res)
  } else if (loginType.value === 'account') {
    if (!validPhone()) {
      return
    }
    if (!validPwd()) {
      return
    }
    const res = await req.post(urls.v1.system.auth.login, {
      userName: pageData.value.mobile,
      password: pageData.value.pwd,
    })
    afterLogin(res)
  }
}

async function searchMenuList() {
  const res: any = await req.post(urls.v1.system.resource.list)
  // 页面类型的才能出现在左侧菜单中
  const menuList = buildTree(
      res.data.map((item) => ({ ...item, index: item.uniqueProp, title: item.label })),
      {
        idKey: 'uniqueProp',
        pIdKey: 'parentUniqueProp',
      },
  ).filter(item => item.type === '1')
  globalStore.setMenuList(menuList)
}

async function afterLogin(res) {
  localStorage.setItem(TOKEN_KEY, res.data)
  const userRes = await req.get(urls.v1.system.auth.currentUser)
  const userInfo = JSON.stringify(userRes.data)
  localStorage.setItem(USERINFO_KEY, userInfo)
  // 查询当前用户的菜单列表
  await searchMenuList()
  tip({ message: '登录成功', type: 'success' })
  router.push({
    name: 'userList',
  })
  return
}

function validPwd() {
  if (!pageData.value.pwd) {
    tip({ message: '请输入密码', type: 'warning' })
    return false
  }
  return true
}

function validVerifyCode() {
  if (!pageData.value.verifyCode) {
    tip({ message: '请输入短信验证码', type: 'warning' })
    return false
  }
  return true
}

function validPhone() {
  // 判断手机号是否正确
  if (!regexp.mobile.test(pageData.value.mobile)) {
    tip({ message: '请输入正确的手机号', type: 'warning' })
    return false
  }
  return true
}

function handleSendVerifyCode() {
  if (!validPhone()) {
    return
  }

  pageData.value.showSendMsgBtn = false
  pageData.value.restTime = 59
  const t = setInterval(() => {
    pageData.value.restTime = pageData.value.restTime - 1
    if (pageData.value.restTime === 0) {
      pageData.value.showSendMsgBtn = true
      clearInterval(t)
    }
  }, 1000)
}

function handleClickBack() {
  handleChangeLoginType('account')
}

function handleRegister() {
  handleChangeLoginType('verifyCode')
}
</script>
<style lang="less">
.login-form-wrap {
  width: 348px;

  .login-title {
    font-size: 20px;
    font-weight: bold;
    margin-bottom: 20px;
    text-align: center;
  }

  .login-box {
    background-color: #fff;
    border-radius: 10px;
  }

  .login-form-content {
    padding-bottom: 30px;

    &.content-code {
      text-align: center;
    }

    &.content-account,
    &.content-verifyCode {
      padding: 22px;
    }
  }

  .login-input-mobile,
  .login-input-pwd,
  .login-input-verify-code {
    margin-bottom: 22px;

    .el-input {
      border: none;
      font-size: 16px;
    }

    .el-input__wrapper {
      background-color: #f5f5f6;
      box-shadow: none;
    }

    .el-input__inner {
      background-color: #f5f5f6;
      height: 42px;
    }
  }

  .login-input-verify-code {
    position: relative;

    .el-input__wrapper {
      padding-right: 140px;
    }
  }

  .verify-code-btn {
    position: absolute;
    right: 10px;
    top: 50%;
    margin-top: -12px;
    width: 86px;
  }

  .login-btn-submit {
    margin-bottom: 22px;
  }

  .login-btn-submit .el-button {
    height: 42px;
    width: 100%;
    font-size: 16px;
    border-radius: 10px;
    background-image: linear-gradient(129.12deg, #446dff 0%, rgba(99, 125, 255, 0.75) 100%);
    color: #fff;
    backdrop-filter: blur(24px);
  }

  .login-switch-wrap {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 48px;

    &.verifyCode {
      position: relative;
      justify-content: center;
      font-size: 16px;
      font-weight: bold;
    }

    .back {
      position: absolute;
      left: 22px;
      top: 13px;
      cursor: pointer;
    }
  }

  .login-switch-text {
    background-color: #f5f5f6;
    width: 50%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 16px;
    font-weight: bold;
    cursor: pointer;

    &.left {
      border-top-left-radius: 10px;
    }

    &.right {
      border-top-right-radius: 10px;
    }

    &.active {
      background-color: #fff;
      cursor: default;
    }
  }

  .login-code-img {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 200px;
  }

  .scan-canvas {
    width: 150px;
    height: 150px;
    border: 1px solid #ccc;
    border-radius: 6px;
  }

  .login-change-login,
  .login-forgot-pwd {
    display: flex;
    justify-content: space-between;
    margin-bottom: 22px;
  }

  .login-verify-type,
  .login-forgot {
    cursor: pointer;
  }

  .login-checkbox-auto-login {
    line-height: 30px;
    color: #bbb;

    .el-checkbox {
      vertical-align: -2px;
    }

    .el-checkbox__inner {
      border-radius: 100%;
    }

    .el-checkbox + span {
      margin-left: 5px;
      font-size: 12px;
      cursor: pointer;
    }
  }

  .highlight-text {
    color: #637dff;
    padding: 0 2px;
  }

  .login-register-account {
    color: #637dff;
    cursor: pointer;
  }
}

.large-input-dialog {
  .large-input {
    &.el-input--small .el-input__wrapper .el-input__inner {
      height: 48px;
      font-size: 24px;
    }
  }

  .line-text-item {
    line-height: 24px;
    padding: 10px 0 5px 0;
  }
}
</style>
